package in.iqing.model.db;

import android.content.Context;

import com.lidroid.xutils.DbUtils;
import com.lidroid.xutils.db.sqlite.Selector;
import com.lidroid.xutils.db.sqlite.WhereBuilder;
import com.lidroid.xutils.exception.DbException;

import java.util.ArrayList;
import java.util.List;

import in.iqing.model.bean.Book;
import in.iqing.model.bean.Category;
import in.iqing.model.bean.Chapter;
import in.iqing.model.bean.History;
import in.iqing.model.bean.Volume;
import in.iqing.module.download.BookTask;
import in.iqing.module.download.ChapterTask;
import in.iqing.module.download.ContentTask;


/**
 * Created by neavo on 2014/6/25.
 */

public class BaseDB {
    private static final String TAG = "BaseDB";
    public static final int DB_VERSION = 1;
    public static final String DB_NAME = "iqing";
    protected DbUtils db;
    private Object mMutex = new Object();
    protected Context context;

    protected BaseDB() {
    }

    public void onInitialize(Context ctx) {
        context = ctx;
        db = DbUtils.create(ctx, DB_NAME, DB_VERSION, new ExtDbUpgradeListener());

        try {
            db.configDebug(false);
            db.configAllowTransaction(true);
            db.createTableIfNotExist(Book.class);
            db.createTableIfNotExist(Category.class);
            db.createTableIfNotExist(History.class);
            db.createTableIfNotExist(Volume.class);
            db.createTableIfNotExist(Chapter.class);
            db.createTableIfNotExist(ChapterTask.class);
            db.createTableIfNotExist(ContentTask.class);
            db.createTableIfNotExist(BookTask.class);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public <T> void save(T data) {
        synchronized (mMutex) {
            try {
                db.saveOrUpdate(data);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public <T> void save(List<T> data) {
        synchronized (mMutex) {
            try {
                db.saveOrUpdateAll(data);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public <T> void delete(T data) {
        synchronized (mMutex) {
            try {
                db.delete(data);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public <T> void delete(Class<T> type, WhereBuilder builder) {
        synchronized (mMutex) {
            try {
                db.delete(type, builder);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public <T> List<T> find(Selector selector) {
        synchronized (mMutex) {
            List<T> data = new ArrayList<>();

            try {
                data = db.findAll(selector);
            } catch (Exception e) {
                e.printStackTrace();
            }

            return data;
        }
    }

    public <T> T findFirst(Selector selector) {
        synchronized (mMutex) {
            List<T> data = new ArrayList<>();
            try {
                data = db.findAll(selector.limit(1));
                if (data == null || data.size() == 0) {
                    return null;
                } else {
                    return data.get(0);
                }
            } catch (Exception ignored) {
            }
            return null;
        }
    }

    public <T> T findFirstById(Class<T> clazz, int id) {
        synchronized (mMutex) {
            try {
                Object obj = db.findById(clazz, id);
                if (obj == null) {
                    return null;
                } else {
                    return (T) obj;
                }
            } catch (DbException e) {
                e.printStackTrace();
            }
            return null;
        }
    }

    public void clear(Class clazz) {
        if (clazz == null) {
            return;
        }
        try {
            db.deleteAll(clazz);
        } catch (DbException e) {
            e.printStackTrace();
        }
    }

    public void update(Object entity, String... names) {
        try {
            db.update(entity, names);
        } catch (DbException e) {
            e.printStackTrace();
        }
    }

    public void updateAll(List<?> entities, String... names) {
        try {
            db.updateAll(entities, names);
        } catch (DbException e) {
            e.printStackTrace();
        }
    }

    private class ExtDbUpgradeListener implements DbUtils.DbUpgradeListener {

        @Override
        public void onUpgrade(DbUtils dbUtils, int oldVersion, int newVersion) {
            // ignore update on first version
        }
    }

}
